package com.keepc.licence.config;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import com.keepc.licence.entity.LicenseVerifyParam;
import com.keepc.licence.util.LicenseVerify;

/**
 * 许可证检查监听器，用于在应用程序上下文刷新时进行许可证的安装。
 * 实现了ApplicationListener接口，用于监听ContextRefreshedEvent事件。
 */
@Slf4j
@Component
public class LicenseCheckListener implements ApplicationListener<ContextRefreshedEvent> {

    private static final String CLASSPATH_RESOURCE_PREFIX = "classpath:";

    /**
     * 许可证的主题
     */
    @Value("${license.subject}")
    private String subject;

    /**
     * 公钥的别名
     */
    @Value("${license.publicAlias}")
    private String publicAlias;

    /**
     * 访问公钥库的密码
     */
    @Value("${license.storePass}")
    private String storePass;

    /**
     * 证书的生成路径
     */
    @Value("${license.licensePath}")
    private String licensePath;

    /**
     * 密钥库存储路径
     */
    @Value("${license.publicKeysStorePath}")
    private String publicKeysStorePath;

    /**
     * 当上下文被刷新时触发此方法。检查是否为根应用上下文，是则安装证书。
     * 
     * @param event 上下文刷新事件
     */
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 检查是否是根应用上下文，避免在子上下文中重复安装证书
        ApplicationContext context = event.getApplicationContext().getParent();
        if (context == null) {
            if (StringUtils.isNotBlank(licensePath)) {
                log.info("++++++++ 开始安装证书 ++++++++");
                LicenseVerifyParam param = new LicenseVerifyParam();
                // 把证书路径 classpath:license/license.lic 替换为绝对路径
                if (licensePath.startsWith(CLASSPATH_RESOURCE_PREFIX)) {
                    try {
                        licensePath = new ClassPathResource(licensePath.replaceAll(CLASSPATH_RESOURCE_PREFIX, ""))
                                .getFile().getAbsolutePath();
                    } catch (IOException e) {
                        throw new RuntimeException("证书文件不存在");
                    }
                }
                // 把密钥库路径 classpath:license/publicCerts.keystore 替换为绝对路径
                if (publicKeysStorePath.startsWith(CLASSPATH_RESOURCE_PREFIX)) {
                    try {
                        publicKeysStorePath = new ClassPathResource(
                                publicKeysStorePath.replaceAll(CLASSPATH_RESOURCE_PREFIX, ""))
                                .getFile().getAbsolutePath();
                    } catch (IOException e) {
                        throw new RuntimeException("公钥库文件不存在");
                    }
                }

                param.setSubject(subject);
                param.setPublicAlias(publicAlias);
                param.setStorePass(storePass);
                param.setLicensePath(licensePath);
                param.setPublicKeysStorePath(publicKeysStorePath);
                LicenseVerify licenseVerify = new LicenseVerify();
                // 安装证书
                licenseVerify.install(param);
                log.info("++++++++ 证书安装结束 ++++++++");
            }
        }
    }
}